using System.Data;
using System.Collections;
using Microsoft.VisualBasic;
using System.Diagnostics;
using Microsoft.ReportingServices.ReportRendering;
using System;


namespace CustomExcelRenderCS
{

    internal class MatrixCache
    {
        #region class variables
        /// <summary>
        /// start rown of matrix data area
        /// </summary>
        internal double matrixStartRow;
        /// <summary>
        /// end row of matrix data area
        /// </summary>
        internal double matrixEndRow;
        /// <summary>
        /// start column of matrix data area
        /// </summary>
        internal double matrixStartCol;
        /// <summary>
        /// end column of matrix data area
        /// </summary>
        internal double matrixEndCol;
        #endregion
        /// <summary>
        /// flag to indicate if values have been cached for current matrix object
        /// </summary>
        internal bool matrixCacheRecorded;
        /// <summary>
        /// current column of matrix data area
        /// </summary>
        internal double matrixCurCol;
        /// <summary>
        /// current column of matrix data area
        /// </summary>
        internal double matrixCurRow;
        /// <summary>
        /// flag indicating if it is ready for applying sum up formula generating
        /// </summary>
        internal bool isReadyForSumUp;
        /// <summary>
        /// counter used by matrix load
        /// </summary>
        internal int mCounter;
    }

	internal class MatrixRenderer
	{

        /// <summary>
        /// offset to forest row of data area
        /// </summary>
		private int RowOffset = 0;
        /// <summary>
        /// offset to first row of data area
        /// </summary>
        private int ColOffset = 0;
        public MatrixCache matrixCache;

		internal MatrixRenderer()
		{
            matrixCache = new MatrixCache();
		}

        /// <summary>
        /// render method of Matrix object, called be Rendereer
        /// </summary>
        /// <returns>generated html string of matrix object</returns>
		protected internal string Render(Microsoft.ReportingServices.ReportRendering.Matrix reportMatrix)
		{
            // register to renderer record of current matrix
            Renderer.reportRenderCache.currentObjParent = reportMatrix.Name;
            Renderer.reportItemHashTable.Add(reportMatrix.Name, matrixCache);
			
			int lastRow = 0;
			int lastCol = 0;
			
			string[] rContent= new string[reportMatrix.CellRows];
			string[] cContent= new string[reportMatrix.CellColumns];
			
			
			System.Text.StringBuilder pHtml = new System.Text.StringBuilder();

            #region retrieve data from matrix object
            this.RenderMatrixRowMembersCollection(0, rContent, reportMatrix.RowMemberCollection, ref lastRow);
			this.RenderMatrixColMembersCollection(0, cContent, reportMatrix.ColumnMemberCollection, ref lastCol);
            matrixCache.matrixEndRow = lastRow;
            matrixCache.matrixEndCol = lastCol;
            #endregion

            #region process retrieved matrix data and render to output stream
            StyleHandler sh = new StyleHandler(reportMatrix.Style);
			pHtml.AppendFormat("<TABLE BORDER=\"0\" CELLSPACING=\"0\" CELLPADDING=\"0\">");
			cContent[0] = "<TD ROWSPAN=\"" + (ColOffset + 1).ToString() + "\" COLSPAN=\"" + (RowOffset + 1).ToString() + "\">" + Renderer.RenderReportItem(reportMatrix.Corner) + "</TD>" + cContent[0];
			foreach (string c in cContent)
			{
				if (c != null&& c != "")
				{
					pHtml.Append("<TR>" + c + "</TR>");
				}
				
			}
			
			
			for (int r = 0; r <= reportMatrix.CellRows - 1; r++)
			{
				pHtml.Append("<TR>");
				pHtml.Append(rContent[r]);
                int colSpan = 1;
				for (int c = 0; c <= lastCol; c++)
				{
                    Microsoft.ReportingServices.ReportRendering.MatrixCellCollection mc = reportMatrix.CellCollection;
                    sh = new StyleHandler(mc[r, c].ReportItem.Style);

                    ReportItem rItem = mc[r, c].ReportItem as ReportItem;

                    if (rItem !=null)
                    {
                        colSpan = (int)(rItem.Width.ToInches() / Renderer.standardCellWidth);

                    }

					pHtml.Append(string.Format("<TD STYLE=\"{0}\" {1}>", sh.GetHtmlStyleString(typeof(Microsoft.ReportingServices.ReportRendering.Matrix)),colSpan>1?" colspan=\"" + colSpan+"\"":"" ));
                    pHtml.Append(string.Format("<FONT STYLE=\"{0}\">", sh.GetHtmlStyleString(mc[r, c].ReportItem.GetType())));
                    if (mc[r, c].ReportItem != null)
					{
                        // when it comes to the last row of matrix, apply formula computing, save value for cache
                        if (r == reportMatrix.CellRows -1 )
                        {                                                     
                                matrixCache.isReadyForSumUp = true;
                                matrixCache.matrixCurCol = RowOffset + 1 + c;
                            if (!matrixCache.matrixCacheRecorded)
                            {
                                matrixCache.matrixCacheRecorded = true;
                                matrixCache.matrixStartRow = Renderer.globalTrackingRow + RowOffset + 1;
                                matrixCache.matrixEndRow = matrixCache.matrixStartRow + reportMatrix.CellRows - 2;
                                matrixCache.matrixStartCol = RowOffset + 1 + c;                                
                            }
                        }
                        else    // do not apply sum up formula for rows other than last row
                        {
                            matrixCache.isReadyForSumUp = false;
                        }
                        // process current matrix cell, get formulas if applicable, then write to output stream                        
                        pHtml.Append(Renderer.RenderReportItem(mc[r, c].ReportItem));
						
					}
					else
					{
						
						pHtml.Append("&nbsp;");
					}
					pHtml.Append("</FONT></TD>");
				}
				
				pHtml.Append("</TR>");
			}
			
			
			pHtml.Append("</TABLE>");
            #endregion

            return pHtml.ToString();						
		}
		private string[] RenderMatrixRowMembersCollection(int level, string[] rContent, Microsoft.ReportingServices.ReportRendering.MatrixMemberCollection mColl, ref int LastRow)
		{
			System.Text.StringBuilder pHtml = new System.Text.StringBuilder();
            StyleHandler sh = null;
			
			for (int i = 0; i <= mColl.Count - 1; i++)
			{
				if (mColl[i].ReportItem != null)
				{
                    sh = new StyleHandler(mColl[i].ReportItem.Style);
					
					rContent[mColl[i].MemberCellIndex] += string.Format("<TD ROWSPAN=\"{0}\" COLSPAN=\"{1}\" BGCOLOR=\"" + sh.GetStyleColorRGBCode("BackgroundColor") + "\" STYLE=\"{2}\">", mColl[i].RowSpan.ToString(), mColl[i].ColumnSpan.ToString(), sh.GetHtmlStyleString(typeof(Microsoft.ReportingServices.ReportRendering.Matrix)));

                    rContent[mColl[i].MemberCellIndex] += Renderer.RenderReportItem(mColl[i].ReportItem);
					rContent[mColl[i].MemberCellIndex] += "</TD>";
					if (mColl[i].MemberCellIndex > LastRow)
					{
						LastRow = mColl[i].MemberCellIndex;
					}
					
					
					if ( mColl[i].Children != null)
					{
						if (RowOffset == level)
						{
							RowOffset++;
						}
						this.RenderMatrixRowMembersCollection(level + 1, rContent, mColl[i].Children, ref LastRow);
					}
				}
				
			}
			
			return rContent;
		}
		
		private string[] RenderMatrixColMembersCollection(int level, string[] cContent, Microsoft.ReportingServices.ReportRendering.MatrixMemberCollection mColl, ref int LastCol)
		{
			System.Text.StringBuilder pHtml = new System.Text.StringBuilder();
            StyleHandler sh = null;
			
			for (int i = 0; i <= mColl.Count - 1; i++)
			{
				if (mColl[i].ReportItem != null)
				{
                    sh = new StyleHandler(mColl[i].ReportItem.Style);
                    cContent[level] += string.Format("<TD ROWSPAN=\"{0}\" COLSPAN=\"{1}\" BGCOLOR=\"{2}\" STYLE=\"{3}\">{4}</TD>", mColl[i].RowSpan.ToString(), mColl[i].ColumnSpan.ToString(), sh.GetStyleColorRGBCode("BackgroundColor"), sh.GetHtmlStyleString(typeof(Microsoft.ReportingServices.ReportRendering.Matrix)), Renderer.RenderReportItem(mColl[i].ReportItem));
					if (mColl[i].MemberCellIndex > LastCol)
					{
						LastCol = mColl[i].MemberCellIndex;
					}
					
					
					if (mColl[i].Children != null)
					{

						if (ColOffset == level)
						{
							ColOffset++;
						}
						
						this.RenderMatrixColMembersCollection(level + 1, cContent, mColl[i].Children, ref LastCol);
					}
					
				}
				
			}
			
            return cContent;
			
		}
		
	}
	
	
	
}
